package com.aboo.infrastructure.redis.service.impl;

import com.aboo.infrastructure.redis.po.Cell;
import com.aboo.infrastructure.redis.service.RedisService;
import com.aboo.infrastructure.redis.frame.util.RedisUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class RedisServiceImpl implements RedisService {

    private static int SECOND_TIME = 5;
    private static long ACCESS_NUM = 3L;

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public boolean limit(String userId, String method) {
        String key = "api:limit:" + userId + ":" + method;
        Long count = redisUtils.incr(key, 1);
        if (count == 1L) {
            redisUtils.expire(key, SECOND_TIME);
            return false;
        } else if (count > ACCESS_NUM) {
            return true;
        }

        return false;
    }

    @Override
    public String getSetRedisStr() {
        String redisKey = "testKey";
        String redisVal = "testVal";
        redisUtils.saveString(redisKey, redisVal, 10);
        String data = redisUtils.get(redisKey);

        return data;
    }

    @Override
    public Cell getSetRedisObj() {
        Cell org = new Cell("008", 18, new BigDecimal("25.65"));
        redisUtils.saveObject("testObjKey", org, 80);
        Cell sen = (Cell) redisUtils.getObject("testObjKey");

        return sen;
    }

    @Override
    public String incrRedis() {
        String redisKey = "incrKey";
        long redisVal = redisUtils.incr(redisKey, 1L);

        return String.valueOf(redisVal);
    }

    @Override
    public void geo() {
        String geoKey = "aboo:geo";
        redisUtils.delKey(geoKey);

        RedisGeoCommands.GeoLocation<String> xuanwu = new RedisGeoCommands.GeoLocation<>("xuanwu", new Point(118.802747, 32.055187));
        RedisGeoCommands.GeoLocation<String> qinghuai = new RedisGeoCommands.GeoLocation<>("qinghuai", new Point(118.800016, 32.042945));
        RedisGeoCommands.GeoLocation<String> jiangning = new RedisGeoCommands.GeoLocation<>("jiangning", new Point(118.850896, 31.95794));
        RedisGeoCommands.GeoLocation<String> yuhua = new RedisGeoCommands.GeoLocation<>("yuhua", new Point(118.769833, 32.009639));
        RedisGeoCommands.GeoLocation<String> gulou = new RedisGeoCommands.GeoLocation<>("gulou", new Point(118.770121, 32.083093));
        RedisGeoCommands.GeoLocation<String> pukou = new RedisGeoCommands.GeoLocation<>("pukou", new Point(118.708892, 32.118819));
        RedisGeoCommands.GeoLocation<String> liuhe = new RedisGeoCommands.GeoLocation<>("liuhe", new Point(118.811802, 32.333124));
        List<RedisGeoCommands.GeoLocation<String>> geoList = Lists.newArrayList(xuanwu, qinghuai, jiangning, yuhua, gulou, pukou, liuhe);
        redisTemplate.opsForGeo().add(geoKey, geoList);
        redisTemplate.expire(geoKey, 60, TimeUnit.MINUTES);

        Point centerPoint = new Point(118.783919, 32.076729);
        Circle circle = new Circle(centerPoint, new Distance(10000, Metrics.NEUTRAL));
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius(geoKey, circle, args);

        Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = results.iterator();
        while (iterator.hasNext()) {
            GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
            RedisGeoCommands.GeoLocation<String> geoLocation = geoResult.getContent();

            // 区域名称
            String regionName = geoLocation.getName();
            // 经度
            String longitude = String.valueOf(geoLocation.getPoint().getX());
            // 纬度
            String latitude = String.valueOf(geoLocation.getPoint().getY());
            // 距离（米）
            Integer distance = BigDecimal.valueOf(geoResult.getDistance().getValue()).setScale(0, RoundingMode.HALF_UP).intValue();

            log.info("regionName:{},longitude:{},latitude:{},distance:{}", regionName, longitude, latitude, distance);
        }
    }

}
